package com.tsd.jxc.fin.job;

import com.tsd.core.annotation.TaskJob;
import com.tsd.core.annotation.TaskJobMethod;
import com.tsd.core.constants.Constants;
import com.tsd.core.datasource.DataSourceContextHolder;
import com.tsd.core.job.JobBaseClass;
import com.tsd.core.thread.ThreadPoolTaskUtil;
import com.tsd.core.utils.DoubleUtil;
import com.tsd.core.utils.ExceptionUtil;
import com.tsd.core.utils.HlpUtils;
import com.tsd.core.utils.RefectUtil;
import com.tsd.job.entity.SysTaskJobExt;
import com.tsd.job.service.SysTaskJobExecLogService;
import com.tsd.jxc.fin.FinanceConstants;
import com.tsd.jxc.fin.dao.JxcFinanceAccountDetailMapper;
import com.tsd.jxc.fin.dao.JxcFinanceAccountMapper;
import com.tsd.jxc.fin.dao.JxcFinanceQueMapper;
import com.tsd.jxc.fin.entity.JxcFinanceAccountDetail;
import com.tsd.jxc.fin.entity.JxcFinanceAccountExt;
import com.tsd.jxc.fin.entity.JxcFinanceQueExt;
import com.tsd.system.entity.SysUser;
import com.tsd.system.service.SysAccountSetService;
import com.tsd.utils.AutoInjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;

/**
 * @ClassName: JxcFinanceJob
 * @Description: TODO
 * @Author: Hillpool
 * @Date: 2022/9/2 16:40
 * @Version: 1.0
 */
@TaskJob(name = "账单定时任务", mode = FinanceConstants.MODE_JXC)
public class JxcFinanceJob extends JobBaseClass {

    public static final Logger LOGGER = LoggerFactory.getLogger(JxcFinanceJob.class);
    /**
     * 处理库存处理队列
     */
    private static boolean isStartProcJxcFinanceQueing = false;
    @Resource
    private SysAccountSetService sysAccountSetService;
    @Resource
    private SysTaskJobExecLogService sysTaskJobExecLogService;
    @Resource
    private JxcFinanceQueMapper jxcFinanceQueMapper;
    @Resource
    private JxcFinanceAccountMapper jxcFinanceAccountMapper;
    @Resource
    private JxcFinanceAccountDetailMapper jxcFinanceAccountDetailMapper;

    public void addJxcFinanceQue(String code, String bizName, String method, Long dataId, SysUser opUser) {
        JxcFinanceQueExt queExt = new JxcFinanceQueExt();
        queExt.setProc_type(1);
        queExt.setCode(code);
        queExt.setBiz_name(bizName);
        String beanName = HlpUtils.toLowerCaseFirstOne(JxcFinanceJob.class.getSimpleName());
        queExt.setBean_name(beanName);
        queExt.setMethod_name(method);
        queExt.setData_id(dataId);
        queExt.setState(Constants.VALUE_NO);
        AutoInjectUtils.autoInjectBaseData(queExt, opUser, AutoInjectUtils.TYPE_CREATE);
        jxcFinanceQueMapper.insertSelective(queExt);
    }

    /**
     * 加入优先队列
     *
     * @param accountSetSid
     */
    public void addAccountSet2PriorityQueue4Finance(String accountSetSid) {
        // 加入优先队列
        super.addPpriorityQueue(accountSetSid);
        // 启动
        ThreadPoolTaskUtil.execute(() -> {
            startProcJxcFinanceQue(null);
        });
    }

    @TaskJobMethod(name = "处理账单队列")
    public void startProcJxcFinanceQue(SysTaskJobExt jobExt) {
        LOGGER.info("处理账单队列：startProcJxcFinanceQue");
        if (!isStartProcJxcFinanceQueing) {
            isStartProcJxcFinanceQueing = true;
            super.fetchAccountSet("处理账单队列", this.getClass().getName(), "startProcJxcFinanceQue", new CallBack() {
                @Override
                public int dealBody() {
                    procJxcFinanceQue();
                    return 0;
                }

                @Override
                public void complete() {
                    isStartProcJxcFinanceQueing = false;
                }
            });
        }
    }

    public void procJxcFinanceQue() {
        LOGGER.info("账套：{}，处理账单队列：procJxcFinanceQue", DataSourceContextHolder.getDataSourceType());
        int pageSize = 100;
        List<JxcFinanceQueExt> queExtList;
        Long greaterThanId = null;
        do {
            queExtList = jxcFinanceQueMapper.select4Proc(greaterThanId, pageSize);
            if (HlpUtils.isEmptyList(queExtList)) {
                break;
            }
            for (JxcFinanceQueExt queExt : queExtList) {
                this.procOneRecordByRefect(queExt);
            }
            greaterThanId = queExtList.get(queExtList.size() - 1).getId();
        } while (queExtList.size() == pageSize);
    }

    private synchronized void procOneRecordByRefect(JxcFinanceQueExt queExt) {
        try {
            try {
                RefectUtil.springInvokeMethod(queExt.getBean_name(), queExt.getMethod_name(), new Object[]{queExt});
                queExt.setState(1);
                queExt.setResult_text(null);
            } catch (Exception e) {
                queExt.setState(-1);
                queExt.setResult_text(ExceptionUtil.getStackTraceFromException(e));
            }
            queExt.setUpdate_date(new Date());
            jxcFinanceQueMapper.updateByPrimaryKey(queExt);
        } catch (Exception e) {
            LOGGER.error(ExceptionUtil.getStackTraceFromException(e));
        }
    }

    public void updateFinanceAmount(JxcFinanceQueExt queExt) {
        JxcFinanceAccountDetail detail = jxcFinanceAccountDetailMapper.selectByPrimaryKey(queExt.getData_id());
        if (detail == null) {
            return;
        }
        JxcFinanceAccountExt accountExt;
        List<JxcFinanceAccountExt> accountExtList = jxcFinanceAccountMapper.selectValidByPartyList(Collections.singletonList(detail.getRelated_party_sid()));
        if (HlpUtils.isEmptyList(accountExtList)) {
            accountExt = new JxcFinanceAccountExt();
            accountExt.setRelated_party_sid(detail.getRelated_party_sid());
        } else {
            accountExt = accountExtList.get(0);
        }
        if (HlpUtils.isEmpty(accountExt.getAmount())) {
            accountExt.setAmount(BigDecimal.ZERO);
        }
        double amount = accountExt.getAmount().doubleValue();
        String operate = FinanceConstants.getAccountTypeOp(DataSourceContextHolder.getDataSourceType(), detail.getBill_type());
        if (FinanceConstants.QUEUE_OP_INSERT.equals(queExt.getCode())) {
            if (FinanceConstants.OP_ADD.equals(operate)) {
                amount = DoubleUtil.add(amount, FinanceConstants.getAmount(detail));
            } else if (FinanceConstants.OP_SUB.equals(operate)) {
                amount = DoubleUtil.sub(amount, FinanceConstants.getAmount(detail));
            }
        } else {
            if (FinanceConstants.OP_ADD.equals(operate)) {
                amount = DoubleUtil.sub(amount, FinanceConstants.getAmount(detail));
            } else if (FinanceConstants.OP_SUB.equals(operate)) {
                amount = DoubleUtil.add(amount, FinanceConstants.getAmount(detail));
            }
        }
        accountExt.setAmount(BigDecimal.valueOf(amount));
        if (HlpUtils.isEmpty(accountExt.getId())) {
            AutoInjectUtils.autoInjectBaseData(accountExt, null, AutoInjectUtils.TYPE_CREATE);
            jxcFinanceAccountMapper.insertSelective(accountExt);
        } else {
            AutoInjectUtils.autoInjectBaseData(accountExt, null, AutoInjectUtils.TYPE_UPDATE);
            jxcFinanceAccountMapper.updateByPrimaryKeySelective(accountExt);
        }
    }
}
